#!/usr/bin/env python
# Author: mingzhong.huang

import requests
import json
import  pandas  as pd
from core.logger import logger
from setting import config

class ConsulClient():
    """  consul client
    """
    def __init__(self):
        self.url=config.CONSUL_URL
        self.header = {
            "X-Consul-Token": config.CONSUL_TOKEN,
            "Content-Type": "application/json"
        }

    def get_consul_data(self,consul_data):
        data={
            "ID": f"{consul_data['uuid']}",
            "Name": "node-exporter",
            "Tags": ["node-exporter"],
            "Address": str(consul_data["ip"]),
            "Port": consul_data["port"],
            "Meta": consul_data["labels"],
            "EnableTagOverride": False,
            "Check": {
               "HTTP": f"{consul_data['scheme']}://{ consul_data['ip'] }:{ consul_data['port'] }/{consul_data['metrics']}",
               "Interval": "10s"
            },
            "Weights": {
                "Passing": 10,
                "Warning": 1
            }
        }
        return json.dumps(data)

    def create_consul_service(self,consul_data):
        try:
            service = self.get_consul_service_by_id(consul_data["uuid"])
            if service:
                url = f"http://{service['Address']}:8500/v1/agent/service/register?replace-existing-checks=1"
            else:
                url = self.url + "/v1/agent/service/register?replace-existing-checks=1"
            data = self.get_consul_data(consul_data)
            req = requests.put(url=url,data=data, headers=self.header)
            if req.status_code != 200:
                logger.error(f"create consul service:{consul_data['uuid']} failed =>{req.text}")
                return False

        except Exception as e:
            logger.error(f"create consul service:{consul_data['uuid']} error => {e}")
            return False

        logger.info(f"create consul service:{consul_data['uuid']} success")
        return True


    def delete_consul_service(self,serviceid):
        service = self.get_consul_service_by_id(serviceid)
        if not service:
            logger.warning(f"delete service id:{serviceid} nothing")
            return True

        try:
            url = f"http://{service['Address']}:8500/v1/agent/service/deregister/{serviceid}"
            req = requests.put(url=url, headers=self.header)
            if req.status_code != 200:
                logger.error(f"delete consul service:{serviceid} failed => {req.text}")
                return False
        except Exception as e:
            logger.error(f"delete consul service:{serviceid} error =>{e}")
            return False

        logger.info(f"delete consul service:{serviceid} success")
        return True


    def get_consul_service(self, service_name):
        try:
            url = self.url + f'/v1/catalog/service/{service_name}'
            req =requests.get(url=url, headers=self.header)
            if req.status_code != 200:
                logger.error(f"get consul service:{service_name} failed => {req.text}")
                return False
        except Exception as e:
            logger.error(f"get consul service:{service_name} error =>{e}")
            return False

        logger.info(f"get consul service:{service_name} success")
        return json.loads(req.text)

    def get_consul_service_by_id(self, service_id):
        services_info = self.get_consul_service("node-exporter")
        if not services_info:
            logger.warning(f"get consul service by id failed")
            return False

        for service in services_info:
            if str(service_id) == service["ServiceID"]:
                return service

        logger.warning(f"serviceid:{service_id} not in consul")
        return False


    def get_consul_service_by_ip(self, service_ip):
        services_info = self.get_consul_service("node-exporter")
        for service in services_info:
            if service_ip == service["ServiceAddress"]:
                return service

        logger.warning(f"service_ip:{service_ip} not in consul")
        return None


    def get_consul_unhealthy_service(self):
        try:
            url = self.url + f'/v1/health/state/critical'
            req =requests.get(url=url, headers=self.header)
            if req.status_code != 200:
                logger.error(f"get consul unhealthy service failed => {req.text}")
                return None

            result = json.loads(req.text)
        except Exception as e:
            logger.error(f"get consul unhealthy service error => {e}")
            return None

        logger.info("get consul unhealthy service success")
        return result

    def get_consul_unhealthy_service_to_excel(self):
        # 获取不健康的服务，只有服务id
        unhealthy_services = self.get_consul_unhealthy_service()
        if not unhealthy_services:
            return False

        # 获取所有的服务，包含所有的信息
        all_services = self.get_consul_service("node-exporter")
        if not all_services:
            return False
        all_services_id = {
            service['ServiceID']: service
            for service in all_services
        }

        unhealthy_data = []
        for unhealthy_service in unhealthy_services:
            service = all_services_id[unhealthy_service["ServiceID"]]
            unhealthy_data.append({
                "id": service["ServiceID"],
                "name": service["ServiceMeta"]["hostname"],
                "ip": service["ServiceAddress"],
                "port": service["ServicePort"],
                "center": service["ServiceMeta"]["center"],
                "department": service["ServiceMeta"]["department"],
                "host_group": service["ServiceMeta"]["host_group"]
            })

        df = pd.DataFrame(unhealthy_data)
        df.to_excel(f"unhealthy_service.xlsx", index=False)


def main():
    consul = ConsulClient()
    # data = consul.get_consul_service("node-exporter")
    consul.get_consul_unhealthy_service_to_excel()

    # consul.delete_consul_service(442)


if __name__ == "__main__":
    main()
